package com.flyan.game.motafx.entity;

import cn.hutool.json.JSONUtil;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import com.flyan.game.motafx.component.BackpackComponent;
import com.flyan.game.motafx.component.LifePanelComponent;
import com.flyan.game.motafx.component.character.BraveComponent;
import com.flyan.game.motafx.component.item.ItemComponent;
import com.flyan.game.motafx.component.monster.MonsterComponent;
import com.flyan.game.motafx.component.npc.NpcComponent;
import com.flyan.game.motafx.core.consts.PropertyConsts;
import com.flyan.game.motafx.core.enums.EntityTypeEnum;
import com.flyan.game.motafx.core.pojo.LifePanel;
import com.flyan.game.motafx.core.util.entity.EntityUtils;
import com.flyan.game.motafx.effect.item.EquipEffect;
import com.flyan.game.motafx.entity.character.CharacterEntityInfo;
import com.flyan.game.motafx.entity.character.CharacterInfo;
import com.flyan.game.motafx.entity.character.CharacterTable;
import com.flyan.game.motafx.entity.item.ItemEntityInfo;
import com.flyan.game.motafx.entity.monster.MonsterEntityInfo;
import com.flyan.game.motafx.entity.monster.MonsterInfo;
import com.flyan.game.motafx.entity.monster.MonsterTable;
import com.flyan.game.motafx.entity.npc.NpcEntityInfo;

import static com.almasb.fxgl.dsl.FXGL.entityBuilder;

/**
 * 魔塔实体工厂
 *
 * @author flyan
 * @version 1.0
 * @email flyan_by_chenu@sina.com
 * @since 2025/2/10
 */
public class MotaEntityFactory implements EntityFactory {

    private final CharacterTable characterTable = new CharacterTable();
    private final MonsterTable monsterTable = new MonsterTable();

    /**
     * 角色
     */
    @Spawns("CHARACTER")
    public Entity CHARACTER(SpawnData data) {
        CharacterEntityInfo info = EntityUtils.getEntityInfoFromSpawnData(data, CharacterEntityInfo.class);
        EntityTypeEnum type = EntityTypeEnum.valueOfCode(info.getEntityCode());
        assert type != null;
        CharacterInfo characterInfo = characterTable.get(type);

        /* 生命面板，若生成参数未特殊指定，从角色表中初始化 */
        LifePanel lifePanel = info.getObject("lifePanel", LifePanel.class);
        if (lifePanel == null) {
            lifePanel = characterInfo.getLifePanel();
        }

        return entityBuilder(data)
                .type(type)
                .with(new BraveComponent()) // 勇士角色组件
                .with(new LifePanelComponent()
                        .setLifePanel(lifePanel))
                .with(new BackpackComponent()) // 背包组件
                .zIndex(type.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * npc
     */
    @Spawns("NPC")
    public Entity NPC(SpawnData data) {
        NpcEntityInfo info = EntityUtils.getEntityInfoFromSpawnData(data, NpcEntityInfo.class);
        EntityTypeEnum type = EntityTypeEnum.valueOfCode(info.getEntityCode());
        assert type != null;
        return entityBuilder(data)
                .type(type)
                .with(new NpcComponent())
                .zIndex(type.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 怪物
     */
    @Spawns("MONSTER")
    public Entity MONSTER(SpawnData data) {
        MonsterEntityInfo info = EntityUtils.getEntityInfoFromSpawnData(data, MonsterEntityInfo.class);
        EntityTypeEnum type = EntityTypeEnum.valueOfCode(info.getEntityCode());
        assert type != null;
        MonsterInfo monsterInfo = monsterTable.get(type);

        /* 生命面板，若生成参数未特殊指定，从怪物表中初始化 */
        LifePanel lifePanel = info.getObject("lifePanel", LifePanel.class);
        if (lifePanel == null) {
            lifePanel = monsterInfo.getLifePanel();
            info.putObject("lifePanel", lifePanel);
        }
        data.put(PropertyConsts.ENTITY_INFO, JSONUtil.parseObj(info));

        return entityBuilder(data)
                .type(type)
                .with(new MonsterComponent())
                .with(new LifePanelComponent()
                        .setLifePanel(lifePanel))
                .zIndex(type.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 物品
     */
    @Spawns("ITEM")
    public Entity ITEM(SpawnData data) {
        ItemEntityInfo info = EntityUtils.getEntityInfoFromSpawnData(data, ItemEntityInfo.class);
        EntityTypeEnum type = EntityTypeEnum.valueOfCode(info.getEntityCode());
        assert type != null;

        /* 是装备物品 */
        Boolean isEquip = info.getObject("isEquip", Boolean.class);
        if (Boolean.TRUE.equals(isEquip)) {
            info.addEffect(EquipEffect.class.getName()); // 装备效果
        }
        data.put(PropertyConsts.ENTITY_INFO, JSONUtil.parseObj(info));

        return entityBuilder(data)
                .type(type)
                .with(new ItemComponent())
                .zIndex(type.getZIndex().getIndex())
                .collidable()
                .build();
    }

}
